UNDERSTANDING AND USING THE BIOS DISKETTE SERVICES AT INT 13H OR UNDOCUMENTED QUIRKS OF THE BIOS DISKETTE SERVICES AT INT 13H References: (a) System BIOS for IBM PCs, Compatibles, and EISA Computers by Phoenix Technologies Ltd PROLOGUE: The following is a compilation of experiences by several Assembly language programmers concerning the diskette services (Int 13h) of at least some of the "modern" versions of BIOS in general use. It has been prepared by Charley Martin [72130,1400] in discussion and collaboration with an OUTSTANDING group of very competent and engaging programmers: Dave Angel [75300,1166] Frank Burleigh [72730,1017] Albert Duro [73757,2167] Jim Mack [76630,2012] Ron Smith [71620,514] Eric Tauck [72457,1557] Any programmers are invited to provide additional observations to Charley Martin for inclusion in this discussion for the future reference of all. Much of what is documented here was found by trial and error on various systems at various times. It should be used as GUIDANCE and HINTS as to how to troubleshoot problems, rather than UNIVERSAL TRUTH applicable to all systems. (With the number of companies making I/O hardware and writing BIOS software for it, there does not seem to be a reliable standard of "universal truth".) Most of the ensuing discussion concerns how to use the BIOS with drives capable of two densities of format, i.e., 5.25" drives capable of 1.2M and 3.5" capable of 1.44M operation, and hopes to straighten up some of the confusion we have seen in the documentation. A. READING, WRITING AND VERIFYING ON MULTI-DENSITY DRIVES: For drives with multiple density capability, some of the BIOS diskette services at interrupt 13h, notably services 2 (read), 3 (write), and 4 (verify), seem generally to "take care of themselves" in switching between disk formats, in the sense that the programmer's intervention does not seem to be needed for the BIOS to detect and adjust internally to disk changes, and to be able to find the requested tracks and sectors on whatever media is installed. Here is how it works: The BIOS uses two bytes (the "media bytes") at 0040:0090 and 0040:0091 in the lower BIOS data area to keep a record for itself of the current media in drives A and B, respectively. Ref (a) describes the structure of this byte: Bits 7-6: Data transfer rate: 0=500 KBS (1.44M/1.2M) 1=300 KBS (360k) 2=250 KBS (720k) Bit 5: Double stepping required (only 360k disk in 1.2M) Bit 4: 0=unknown media, 1=known media Bit 3: Reserved Bits 2-0: Media/drive descriptor: 7=720k or 1.44M drive 5=Known 1.2M in 1.2M drive 4=Known 360k in 1.2M drive 3=Known 360k in 360k drive 2=Trying 1.2M in 1.2M drive 1=Trying 360k in 1.2M drive 0=Trying 360k in 360k drive For the common formats and drive combinations, the values of media bytes you would expect to find when the BIOS knows the media type are: 360k in 360k drive: 53h 360k in 1.2M drive: 74h 1.2M in 1.2M drive: 15h 720k in 720k drive: 97h 720k in 1.44M drive: 97h 1.44M in 1.44M drive: 17h When the computer first boots, bit 4 is set to zero. This signals the BIOS that it must determine the format of during the next read/write/verify call on that drive. If you have a tracer or debugger that lets you intercept Int 13h calls, you can actually watch the value of this byte change as the BIOS resets it during the call. Also, if the drive has the capability of sensing media change, on the next read/write/verify call after the door has been cycled open- shut the BIOS will NOT perform the requested operation, but will return to the user an error code 6 in Ah, and will reset bit 4 of the media byte to 0, indicating it no longer knows the media type. If the user repeats the call, which is most often the proper thing to do, the BIOS determines the format of the new media, sets the media byte accordingly (may indeed be different from the starting value), and performs the operation if it can. B. FORMATTING (or, HEREIN LIES THE RUB:) Life in BIOSland gets more confusing when you start formatting disks. For formatting, the BIOS uses an additional set of parameters, called the drive parameter table (DPT), which prescribes the physical details of the track format, and which contains the number of sectors per track, bytes per sector, gap between sectors, format fill byte, and such esoteric drive attributes as motor start time and turnoff delay, head load time, and step rate time. The references report each DPT to be 11 bytes. However, if you look in ROM BIOS you will find each DPT is actually 13 bytes, and the byte at offset 11 is number of tracks on the disk (0-based). The BIOS ROM is imbedded with a table of these parameters for each combination of drive and media type that it has been programmed to recognize. Thus if you have a 5.25" drive capable of 1.2M format, and a 3.5" drive capable of 1.44M, there are four such tables. So that the BIOS can know which of these tables, or even some other table create by a user, is to be used at a given time, a far pointer is reserved for BIOS' use at Interrupt Table position 1Eh (0000:0078). In our experience, in systems with a 1.44M drive, Int 1Eh is loaded at bootup with a pointer to a copy of the DPT for 1.44M disk in 1.44M drive. However, it seems not to matter much, because the DPT pointed to by 1Eh only appears to be referenced by the BIOS during disk formatting, and not during reading/writing/verifying. By experimentation, we have observed that changing the pointer at 1Eh does not seem to affect Int 13h/ Services 2, 3 and 4. The steps to formatting a track are as follows: 1. Setting Media Type for Format (Service 18h): This service must be called before formatting a track on a disk. The title of this service is misleading, however, because its action is incomplete. The user inputs to this service the number of tracks (0-based) and sectors (1-based) desired for the disk (drive in dl). Service 18h determines if the combination is supported by consulting the imbedded DPTs in ROM BIOS, and if so returns in ES:DI a far pointer to the applicable one. 2. Installing the DPT pointer in Int 1Eh: If the call to Service 18h was successful (carry clear, Ah=0), the user must then install this pointer passed back through ES:DI into Int 1Eh. Int 13h/18h does NOT install this pointer, and the documentation available to the public is universally lousy on this point. The following code illustrates steps 1. and 2. above: ... start mov ah,18h mov dl,DRIVE ;define as 0 or 1 with an equ int 13h cmp ah,6 ;change line active? retry je start cmp ah,0 jne no_good mov dx,di ;drive parm table ptr returned via es:di push es pop ds mov ax,251Eh ;install new interrupt pointer int 21h push cs pop ds ... no_good ;error handler ... 3. Setting Up a Track Address Field: Once the format parameters are set by steps 1. and 2. above, we can proceed with formatting a track with Int 13h/Service 05h. But first we have to construct a track address field. When it formats a track, the BIOS places a distinctive mark at the beginning of each sector as a reference for each future operation. This mark for each sector actually carries the following information: track number, sector number, side number and sector size. Tracks are numbered from 0 (ie, are "0-based"), sectors from 1, and side number is 0 or 1. Sector size is a code: 0=128 bytes, 1=256, 2=512 and 3=1024. For the common floppies the code is always 2. But the BIOS is dumb -- it has to be told how to mark each sector on the track. The user does this by passing to Service 05h (format track) the pointer to a array of (4 x number of sectors on a track) bytes. Each 4-byte entry consists of track number (0-based), head number (0-based), sector number (1-based) and sector size code. For a 360k 5.25" disk, for track 5, head 1, this would look like: Track_addr db 5,1,1,2,5,1,2,2,5,1,3,2,5,1,4,2,5,1,5,2,5,1,6,2 db 5,1,7,2,5,1,8,2,5,1,9,2 For an 18-sector format (1.44M 3.5" disk) this field must have another 9 4-byte entries, continuing in sequence. This array has to be modified for each track and head combination before each format track call. The format track call itself formats the entire track. The following code illustrates: mov ah,5 ;format service mov al,SECTORS ;number of sectors per track mov ch,TRACK ;track numnber, 0-based mov dh,HEAD ;head number, 0-based mov dl,DRIVE push ds pop es lea bx,track_addr ;previously adjusted for track and head int 13h jc error cmp ah,0 jne error format_ok ;loop to next head or track ... error ;error handler cmp ah,6 ;disk change line active je change_line ;perhaps a routine to tell user cant replace ;disk in mid-format ... change_line ;change line active handler - drive door opened The track should now be ready for writing. C. OTHER GOOD DOPE COVERED POORLY BY THE BOOKS: This section is a loosely connected collection of observations and advice that is easier to understand against the backdrop of the discussion above, but fits no particular train of thought: 1. Service 08h Returns the Maximum Density Parameters for Drive: This point is somewhat confusing in most references. This service always returns the track and sector parameters and DPT pointer associated with the highest density format the drive is capable of, regardless of the format currently set or the format of the diskette in the drive. 2. Save and Restore Initial Parameters When Formatting Diskettes: In setting up to format a disk using the above steps, before changing the 1Eh pointer in the interrupt table, save the old one. Restore it on exiting the program. The following code illustrates: ... mov ax,351Eh ;get 1E int 21h mov [old_1e],bx mov [old_1e+2],es ... ;Main program ... mov dx,[old_1e] mov ds,[old_1e+2] mov ax,251Eh int 21h push cs pop ds ... old_1e ds 4,0 ;far pointer to initial DPT It seems that if the BIOS was happy with this DPT which the system installed in 1E when it booted, before you interfered by installing a different pointer, it will appreciate getting it back. If the BIOS seems unable to recognize the disk in the drive after you reinstall this DPT pointer, try just cycling the drive door, and failing that put in a disk of the other density. 3. Data Boundary Error (64k) During Formatting: The data boundary error in disk read/write operations is annoying but at least fairly well documented. This is the quirk where the BIOS does not read/write across a 64k RAM segment boundary (called a "DMA page" boundary), and so for Int 13h/2 or /3 calls you must always check that there is room in the DMA page above the pointer you pass in ES:BX to accomodate ALL the sectors you want to transfer. Although no data is transferred during a verify sector call, the BIOS still expects ES:BX to contain an address which COULD accomodate the number of sectors to be verified in the current DMA page. One additional quirk that affects at least the early (c.1985) Tandy BIOS is that this same limitation applies to the pointer used for the track address field in the 13h/5 format track service. As an aside, to keep from crossing a DMA page during an operation, consider the following algorithm for transferring a track's worth of data: - Calculate how many paragraphs is required to transfer one track (number of sectors on track x 32 paragraphs per 512-byte sector), and request allocation of double that from DOS. - Save the returned segment; add the number of paras on a track; AND both segment addresses with 0F000h and compare. If equal, then initial segment address as inside DMA page boundary; if not, then add number of paras on a track. 4. Int 13h Services Do Not Always Return Carry Set on Error: Some older versions of BIOS do not consistently return the carry flag set on error, as most references state. However, for every service except 08h, every version of BIOS seems always to return a non-zero error code in Ah on error. Therefore, there may not be a sure-fire single test for errors with your BIOS. Comparing Ah to 0, as done in the examples above, may need to be supplemented by first checking for carry set. The only service that is consistently documented as returning ONLY carry set on error is service 08h. Sometimes the BIOS does not return carry set because it does not consider the occurrence an error. For example, some BIOSes do not consider crossing a DMA page boundary an "error", but will return Ah=8 (DMA overrun on operation) and Al=some number of sectors less than you had asked to read or write in your call when the buffer pointer you provide results in a DMA page boundary being crossed. In this case, you MUST look at the Ax return as well as the carry flag to see the result of the requested operation. 5. 3.5" Disks Are Different: 3.5" disks are made with two slightly different case designs, depending on the quality of the magnetic media within -- i.e., its formatability in the high density format. High-density (1.44M) disks have a punched-out hole through the corner of the case adjacent to the write-protect slide. Standard-density (720k; more grainy media) disks do not have this punchout. The disk drive has a sensor that looks for this hole, and does not permit formatting at a density other than that corresponding to the presence or absence of the hole. There is a company that advertises a punch that you can punch out a nice clean square hole in the cases of cheaper 720k disks to convert them to 1.44M, on the assumption that "all media these days is of a quality formatable at 1.44M". I don't quite believe it, myself. You can fool the sensor into letting you reformat a 1.44M disk to 720k with a piece of tape or write-protect tab over the hole. If you try to format a high-density track on a standard-density (no punchout) disk, you will receive errors. The same is try the other way. ************************************************************************** The following is a collection of the messages from Charley Martin's TAPCIS saved files that provided the material for this treatise. It is included for completeness, and may contain additional insight into the Int 13h services. It clearly illustrates the synergy of discussions of this sort: ************************************************************************** #: 377127 S0/Outbox File 23-Feb-92 13:27:00 Sb: Int 13h Problems Fm: IBMPRO To: ALL I'm having no success formatting tracks in high-density 5.25 or either density 3.5 floppies, and success with 5.25 @ 40 tracks ONLY on my old Tandy and not on my new machine. Aaarrrghhhhh! You don't go crazy... You inherit it from your BIOS! I precede my calls to service 8 with a call to 17h, or 18h, or even BOTH, like the book says, to establish the track format parameters. The call to service 8 does not return any error indication (carry clear, Ah=0), but the next call to service 3 ON THAT TRACK results in a "sector not found" error. I have found the hard way, just by trial and error, that writing a complete track's worth of data to a preformatted track in 15- or 18-sector format requires TWO separate calls -- the first to write the first nine sectors, the second to get the remaining 6 or 9. But none of the books talk about THAT. So I'm not making that mistake -- my write routines all work on pre-formatted disks. I ALSO found out -- again not written anywhere -- that if the address of the "Sector address field table" is positioned below a 64k segment boundary, within one track's worth of bytes of the boundary, that the call to service 8 will fault on "DMA overrun". Talk about abstruse! BIOS programmers must be sadists! Help, anyone? - Charley Martin #: 69585 S1/Assembler [P] [IBMPRO] 25-Feb-92 11:54:58 Sb: #69432-Int 13h Problems Fm: Barry Gerhardt 76260,1227 To: Charles F. Martin 72130,1400 I've also had trouble reading/writting more than 9 sectors at a time. But I'm sure there's a way around it since DOS seems to be much faster than my routines that do two back-to-back reads. If you find an answer to this issue, please let me know. #: 389722 S0/Outbox File 1-Mar-92 7:22:00 Sb: Int 13h Problems Fm: IBMPRO REP 69585 To: Barry Gerhardt 76260,1227 Barry, Try the trick I mentioned. Break the write into two pieces, one for sectors 1-9 and a second, after adjusting the offset of the pointer to the memory area to be written from, to write sectors 10-15 or 10-18, depending on 5.25 or 3.5 hi density. That seems to work for me, as a not too pleasing workaround to an undocumented quirk (?), but make sure that nowhere in the track's data area in RAM will the BIOS cross a 64K segment boundary. Also, Barry and anyone else who might be wondering, I referred throughout my original diatribe to problems with "service 8". I truly meant service *5*, the format track service, honest -- just a typo, folks! -Charley M #: 70330 S1/Assembler [P] [IBMPRO] 08-Mar-92 21:08:58 Sb: BIOS Int 13h Format Prob Fm: Charles F. Martin 72130,1400 To: ALL A while back I described not being able to format any floppy disk tracks -- 5.25 or 3.5, eithewr density -- on my new computer running an AMI BIOS and DOS 5.0. (I said before it was Phoenix - its not.) Dave Angel suggested I try again describing the problem, this time including some code. I have included a small program written in WASM (sorry Dave - the only Assembler I've ever used is Eric Tauck's Wolfware) that *doesn't* work on my computer for any in-range values of the equ's, and does for my Tandy 1000. I'm going to run into the size limit, I see. This may not be quite kosher, but I'm going to go up with a "BIOS Problem - Pt 2" with the code. The program returns the track verify error code as a return code, and/or you can intercept any of the calls w/ your fav debugger. If anybody sees something I've missed in the register setups or the sequence of calls, let me know. Using similar logic, I have also been unable to format high-density disks on the DOS 3.3 machines at work. Maybe I just keep running into psychopathic BIOSs, but they aint workin like the book says! Dave, my main reference is the Phoenix System BIOS handbook you mentioned, but I have three others -- and *none* of them gives exactly the same syntax on int 13h services!! -Charley #: 70332 S1/Assembler [P] [IBMPRO] 08-Mar-92 21:18:43 Sb: BIOS Problem - Pt 2 Fm: Charles F. Martin 72130,1400 To: ALL ; TEST TO DEMONSTRATE INT 13H SERVICE 5 -- FORMAT TRACK ; Written for Wolfware Assembler WASM ; Charles F. Martin 72130,1400 ; Define segment for track address field at least one tracks worth away ; from next 64k segment boundary up. (One tracks worth is maximum of ; 18 512-byte sectors = 12hx20h paragraphs = 240h paras TRACKS equ 40 TRACK equ 1 SECTORS equ 9 DRIVE equ 0 ;A drive HEAD equ 0 lea ax,last_byte mov cl,4 shr ax,cl inc ax push ds pop dx add ax,dx push ax mov dx,ax add dx,240h ;paras for one 1.44M track and dx,0F000h ;what 64k segment? push dx and ax,0F000h xor ax,dx pop dx pop ax jz seg_ok mov [track_seg],dx jmps setup_track_seg seg_ok mov [track_seg],ax setup_track_seg mov es,[track_seg] ;segment for track address field xor di,di ;offset 0 mov al,TRACK mov ah,HEAD mov bx,201h ;start with sector 1, format 2 (512 bytes per sector) mov cx,18 ;max of 18 sector addresses needed setup_track_loop stosw push ax mov ax,bx stosw pop ax inc bx ;advance sector loop setup_track_loop ; (See BIOS Problem - Pt 2a) #: 70333 S1/Assembler [P] [IBMPRO] 08-Mar-92 21:18:49 Sb: BIOS Problem - Pt 2a Fm: Charles F. Martin 72130,1400 To: ALL ; (BIOS Problem -Pt 2 contd) mov cx,3 ;make three passes at format format_track push cx mov ah,0 mov dl,DRIVE int 13h ;reset drive mov ah,18h ;set diskeette format parameters mov ch,TRACKS ;tracks on disk dec ch ;0-based mov cl,SECTORS int 13h mov ah,5 ;format the track mov al,SECTORS mov ch,TRACK mov dh,HEAD mov es,[track_seg] xor bx,bx int 13h mov ah,4 ;and verify mov al,SECTORS mov cl,1 ;start verify with sector 1 int 13h pop cx cmp ah,0 je leave loop format_track leave mov al,ah ;pass the error code back mov ah,4Ch int 21h track_seg dw 0 last_byte ds 0 #: 402027 S0/Outbox File 9-Mar-92 20:27:00 Sb: Int 13h Problems Fm: IBMPRO REP 69585 To: Barry Gerhardt 76260,1227 Barry, Many apologies... My first response to your request for additional info if I cracked the problem of not being able to write morre than 9 sectors at a time on a track was too hasty, and I was really tired. I didnt understand that you had _already_ worked out the (not very satisfying) workaround of breaking the track write or read into two pieces. So here I went giving you a tip you already had, like a condescending tutor. Sorry, with a sheepish grin. I tried this test. I have written a program that reads a master diskette, any format, and makes an image on the hard drive, and then makes as many copies as you want, serially, to the same drive -- and works fine with preformatted disks. I timed it tonight, and it makes 360s at about 2 tracks per second, average, and 1.2Ms at about 1.5 t/sec. If the drive speed is the same for 360 and 1.2M, then the disk must be having to come back around to to pick up the second clump of sectors, and reading/writing all 15 sectors at once would be a real speed improvement. But I dont know if the disk travels at the same speed for both densities. Do you know? I.e., are we working on a real limitation? -Charley S1 #: 70437 S1/Assembler [P] [IBMPRO] 10-Mar-92 08:36:17 Sb: #70342-BIOS Problem - Pt 2 Fm: Dave Angel 75300,1166 To: Charles F. Martin 72130,1400 You forgot to post those messages as "POST UNFORMATTED", so they word-wrapped lines that weren't indented, except those that follow a blank line. You can see it in the EQU lines as well. I've been experimenting with that code, but no definite luck yet. Function 18h gets a carry on my system (errorcode 00!), so I added the function 17h that some docs demand. However function 4 still gets the error. So I looked at the values pointed to by INT1E, and see that the sectors/track says 12h, which is definitely wrong with a 360k diskette. I plan to try directly setting that one later today, to see whether that helps. I suspect that one is supposed to copy the block returned in [ES:DI] (which is in ROM), to the block pointed to by INT1E. Other comments about the code: You really should be checking status after each I'd do a MOV DL,DRIVE before every BIOS call, just in case something trashed it. (my hard disk is too precious to take chances) On function 5, you don't set CL to 0. It turns out not to matter, but it's a dangerous practice. For completeness, I added the mov ch, TRACK and mov dh,HEAD to the function 4 logic as well. #: 70438 S1/Assembler [P] [IBMPRO] 10-Mar-92 08:36:27 Sb: #70394-Int 13h Problems Fm: Dave Angel 75300,1166 To: Charles F. Martin 72130,1400 There are two motor speeds at work here, depending on what drives you're using. If I remember this right, a 360k drive rotates at 300rpm, or 200ms per revolution. A 1.2mb drive, at either density, rotates at 360rpm, or about 167ms per revolution. The bit rate is 250khz for the first, and either 300khz or 500khz for the second, depending on media type. So the question of whether motor speed affected your timings depends on whether you used the same drive or not. With a high density drive, optimal throughput would be 5 tracks per second. Two things should affect that: head stepping (every other track) takes some time, probably enough time to miss a whole revolution. And if you have to break up the 15-sector track into two requests, that could conceivably take three revolutions. #: 70463 S1/Assembler [P] [IBMPRO] 10-Mar-92 14:37:44 Sb: #70394-Int 13h Problems Fm: Barry Gerhardt 76260,1227 To: Charles F. Martin 72130,1400 1.2M drives spin at 360 R.P.M. 360K (and 720K and 1.44M) drives spin at 300 R.P.M. That might be enough to account for the difference. You say you get about 2 tracks per second. Assuming you meant cylinders, that would be 4 track writes and two track seeks. Given the slow seek time of floppies, I would say you are doing well with your 360K disks. On the other, you are getting the same results as I do -- only about 50% throughput. Try this: Put a large file on a 1.2M disk. Reboot so DOS doesn't have any cache memory of this. Then, type: "COPY nul:" and time it. You should notice that DOS does alot better than you or I are doing. In my tests, DOS was able to transfer 200K from the floppy in 5.5 seconds. With a little math (15 sectors -- 7.5K per track at 6 RPS), the theoretical maximum transfer speed would be 45K / second. So, 200K could be transferred in 4.4 seconds under ideal conditions. Factor in a wasted revolution while seeking (every 30K) and you see that DOS is reading at full tilt. This means DOS is able to read the entire track in one revolution and our best efforts require two. My conclusion is that DOS can read more than 9 sectors per call. I hope someone chimes in with the answer... Barry #: 404049 S0/Outbox File 11-Mar-92 6:09:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70437 To: Dave Angel 75300,1166 Dave and Barry -- I've found the missing link, and its just *incredible* how lousy all the BIOS documentation is on this point. Eric Tauck (probably one of the ten or so smartest guys in the world) tipped me on it. When you call int 18h to set the disk format, **you aren't done**. Dave, you were close looking at the drive parm block pointed to be int 1Eh. After you call 18, you have to stuff the pointer it returns (es:di) INTO 1E! In other words, the descrription of 18h as "set media type" is *really* misleading.. It really only tells you if that format is *supported*, then you have to punch the pointer it returns into 1E. Do you believe that??? I've got 4 books that talk about BIOS servvices to greater or lesser extent, and NONE of them come out and say this. You have to be careful that ah is zero on return from the int 18 call. Dave, you were getting non-zero, but that might be ok if ah was 6 (change line active)? I dont think you need service 17. I trapped all the calls to int 13 that my DOS format.com used, and it only used 18 to set the media type -- but of course what I didnt see going on was the 1E "put". For safety, I am saving the 1E pointer initial value, and restoring it on exit. I'll take the advice on resetting dl each time. Good point -- dont trust them BIOS writers! Gotta run to work, I'll be more coherent another time! --Charley S1 #: 405055 S0/Outbox File 11-Mar-92 22:55:00 Sb: Int 13h Problems Fm: IBMPRO REP 70463 To: Barry Gerhardt 76260,1227 Barry, I dropped a note in to Dave Angel that was meant for you both. I think the key is getting the pointer that the int 13 service 18 returns for a given combination of input track/sector parameters, and then putting that pointer (returned as ES:DI) into the interrupt table at 1E so the floppy controller knows the disk parameters. Some more playing with that today, since I wrote the note this morning, tells me you have to do that, not JUST before a format call, but also before a read, write OR validate in high density if 1Eh was previously set to point to the double-density parm table. (I think DOS must default the pointer at 1Eh back to the 360k double-density table after calls to int 13, and so thats what you get stuck with (max of 9 sectors at a time, corresponding to the double-density format) until you force it to high density.) If I ever get my hands on the scrawny neck of the guy that DIDNT write that down in the BIOS docs... -Charley #: 70592 S1/Assembler [P] [IBMPRO] 12-Mar-92 00:40:01 Sb: #70524-BIOS Problem - Pt 2 Fm: frank burleigh 72730,1017 To: Charles F. Martin 72130,1400 It looks like I missed a useful discussion! I've just finished the guts of my own formatting code. Yes, you must set 1E with the pointer returned from 13h/18h. I haven't found 13h/17h necessary. At first I'd thought it would be sufficient to set 1E to the pointer returned by 13h/8h but the base table returned might be for the wrong media type. Dave Angel has discovered this. You must adjust the sector in CL (and cyls in CH if 1.2mb media) manually before you call 13h/18h. PCFORM, the formatter that comes with PC Tools, sets 1E before formatting each track. Don't know why; I haven't found that necessary. A question: is the base table (pointer to which is returned by 13h/8h and 13h/18h) for a given media type constant across all such drives? For example, will every 1.2mb drive use the same base table? Charles, you may find the ASM code in forum BPROGB, section on TASM, file FMT130.ZIP, useful. #: 70662 S1/Assembler [P] [IBMPRO] 13-Mar-92 00:02:58 Sb: #70592-BIOS Problem - Pt 2 Fm: ALBERT DURO 73757,2167 To: frank burleigh 72730,1017 I've been following this thread with some interest, but without hands-on, it's hard to grasp the details. I can do that if and when the time comes to actually do it, and there will be others who'll want to do this. So I was wondering if Charles or Frank, or someone who's cracked this might at some point care to put the salient points in a library file. I haven't checked, but it would seem that this little "feature" is not much documented, even informally. Thanks. #: 406919 S0/Outbox File 13-Mar-92 5:59:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70592 To: frank burleigh 72730,1017 Frank, I wish I'd talked with you two months ago when I was tearing out what little hair I had left trying to get a 15 sector track formatted! You gotta tell me, where did you learn that int 1E has to be plugged with the required base table pointer _by the programmer_? I couldn't find it in any book, and I had assumed all along since 13/18 is universally called "SET media type..." that that's what it DID! Boy do I feel stupid! I guess the way 13/8 works is that it returns the base table pointer and characteristics for the maximum density media that drive it is capable of handling, and 13/18 returns the pointer to the base table for the disk format combo you want, if it is supported. I doubt that there are differences in base table parms for the same type drives, but I'm not sure how you'd know without interrogating a large sample. The limited sample I've now seen seem the same, but they are all "modern" drives. It probably isnt necessarily so that head load time, motor turn-off delay, head settle time, motor statrt time are always the same. The next experiement will have to be to find out how the device driver responds to odd-ball values of sectors and tracks. Like, copy the base table for 1.2M format, and change byte four from 0Fh to 0Dh. Anybody game? -Charley #: 70737 S1/Assembler [P] [IBMPRO] 13-Mar-92 19:04:49 Sb: #70676-BIOS Problem - Pt 2 Fm: frank burleigh 72730,1017 To: Charles F. Martin 72130,1400 My code doesn't completely work yet, so I don't believe I have really figured it out yet! ;-) I believe I decided to set 1E myself when I saw that 13h/18h didn't actually change it. #: 70849 S1/Assembler [P] [IBMPRO] 14-Mar-92 22:00:14 Sb: #70834-BIOS Problem - Pt 2 Fm: Dave Angel 75300,1166 To: Charles F. Martin 72130,1400 General principle; restore the 1E pointer to the buffer it started at, before exiting the program. You're asking for trouble if you leave it pointing to a buffer within your program, since the next program will wipe that out. Obviously you should not have modified that buffer in low memory anyway. #: 409858 S0/Outbox File 15-Mar-92 6:58:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70849 To: Dave Angel 75300,1166 Dave, Not sure I understand the context of your last message about "You're asking for trouble if you leave it [the last 1E pointer] pointing to a buffer within your program, since the next program will wipe it out." I dont think I have talked in this thread about using a pointer other than one returned by 13/08 or 13/18 for 1E -- and these are always in the BIOS (F000:xxxx) on my system. Enlighten me... At Albert Duro's suggestion, I took a crack at a little treatise on some of the BIOS quirks we've been talking about, and submitted it as a draft in Lib 1 titled BIOS13.TXT for review/addition/editing. Consider it a living document. Have you resolved the problem you were having with 13/18 returning an error? BTW, the problem with just restoring 1E to the as-found value when you exit a program, I would think, is that you dont know for sure what previous drive it was set for? I've found that the only way to keep my 3.5" drive from getting confused by the next DOS call after exiting a program that modified 1E is to set it for max density with a 13/18 call and 1E put. The 5.25" doesnt seem to care about the last call, the 3.5" does. -Charley #: 70903 S1/Assembler [P] [IBMPRO] 15-Mar-92 18:56:27 Sb: #70870-BIOS Problem - Pt 2 Fm: Dave Angel 75300,1166 To: Charles F. Martin 72130,1400 There's another thread going simultaneously in section 13, titled DMA 64k: still broke! where Frank Burleigh and I discussed the need to modify some of the parms in the ROM before pointing the 1E to it. Obviously that implies copying the block to RAM in the program area, changing one or more parms, and then pointing 1E to it. It is in this case where I was warning of the need to restore 1E to point where it originally did, down at 50:xx Sorry I confused the two threads. Since some of the players are the same, I got messed up which was which. Your little treatise (BIOS13.TXT) covers the problem I had with Int 13h, function 18h. Carry was being set, with an error code of 00. I'm still not sure it's safe to just check AH, but I figure by checking both, I can probably safely ignore the case where Carry is set, but AH is still zero. #: 409073 S0/Outbox File 14-Mar-92 17:53:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70737 To: frank burleigh 72730,1017 Frank, I've got a spooky one to add to the list of "hows come Int 13h acts thatta way?..." I've got a 5.25" 1.2M in drive A and 3.5" 1.44M in B. In my mass-copy disk copying program, on exiting, I reset the drive I used for the copy operation to the maximum density format for that drive (the format returned by 13/8) -- in my case always high density. I figured neither drive should care what data format the last call established, as long as it was valid, and that the next user would explicitly check/reset if needed, as I have learned to do. When the 3.5" disk is the one I used, no problem for either drive in subsequent DOS operations. But when the 5.25" is the one used, all subsequent DOS calls to read/write files on B no longer work for 1.44M disks (and maybe 720's -- I didnt have one handy to try) until I explicitly reset ITS format with a 13/18 call & 1E vector put. I think the device driver for the 3.5" doesnt recognize that the pointer in 1E was changed and no longer applies to it, and it is limited in what sectors it can access by the base table pointed to by 1E -- in this case I surmise that it cant see sectors 16,17,18. So it would seem that you need to set 1E with the max parms for the higher capacity disk so that DOS doesnt have a problem? You'd think the DOS writers would have anticipated that someone might change the base table pointer when they werent looking? -Charley #: 409689 S0/Outbox File 15-Mar-92 4:09:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70662 To: ALBERT DURO 73757,2167 Albert, Re your suggestion of a writeup on BIOS diskette service anomalies/quirks, I'm uploading a little text file BIOS13.TXT into LIB 1 as a straw man for any/all to edit, add to, correct, etc. Frank, Dave, anybody else, join in here please. -Charley #: 70871 S1/Assembler [P] [IBMPRO] 15-Mar-92 09:19:48 Sb: #70870-BIOS Problem - Pt 2 Fm: Jim Mack 76630,2012 To: Charles F. Martin 72130,1400 Charles - It shouldn't be tough to get DOS (the BIOS) to restore the DBT. The BIOS maintains a state variable in its low memory area which it uses to determine what action to take when accessing a drive. Just zero the byte which means "media determined" for that drive and you've dropped it to its lowest state (requiring a rebuild of the DBT) on the next access to the drive. The byte at 40:90 is the media state for drive A, at 40:91 for drive B. 40:92 and :93 are the "operation state" for each drive. Watch these under a debugger while switching media in multi-media drives, and you'll quickly see what state corresponds to what. -- Jim #: 410621 S0/Outbox File 15-Mar-92 19:41:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70871 To: Jim Mack 76630,2012 Jim, Thanks for joining, and thanks for the tip. I never would have known that I could tamper with the BIOS low data area without causing some damage, but now I know. There is one thing I don't like about the trick you suggest of zeroing the media type bytes at 40:90 -- the 5.25 drive makes a frightful noise the next time it tries to read if the disk installed is at 360k. It sounds like the head is trying to index all the way to track 79 out of 39, and banging hard against a physical stop??. It does the same thing whether I zero the whole byte or just bit 4 with a "and byte es:[90h],0EFh". I'm sure the device designers had this likelihood in mind, and that it isn't causing any damage, but I can imagine that not many users would continue to use a piece of my software that caused their computer to give out such awful noises. Any thoughts? -Charley #: 70933 S1/Assembler [P] [IBMPRO] 16-Mar-92 08:34:25 Sb: #70909-BIOS Problem - Pt 2 Fm: Jim Mack 76630,2012 To: Charles F. Martin 72130,1400 Charley - I don't know what you're getting there, but it doesn't seem right. You might want also to perform a "reset" call to tell the BIOS that it should try to seek the outer track using the drive's track 0 sensor. Apparently the drive is expecting to single-step but the BIOS thinks it should double-step... take a look at the DBT that's current when this happens to see if it wants double-stepping, maybe? I don't have any of my information handy, so I can't be more specific, sorry. I recall going through the exercise, and I don't recall any noises, so I'm guessing that you're changing more than you should... or maybe less . -- Jim #: 70942 S1/Assembler [P] [IBMPRO] 16-Mar-92 11:03:41 Sb: #70834-BIOS Problem - Pt 2 Fm: frank burleigh 72730,1017 To: Charles F. Martin 72130,1400 Indeed, it's all too strange. In my routine the first thing is do is get int 1E with int 21h/ax=351e and stuff it away somewhere. When I leave, I put it back with 21h/ax=251e. As long as I've been doing that, I don't have problems. Things could clearly be documented better! ;-) #: 412134 S0/Outbox File 16-Mar-92 20:54:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70903 To: Dave Angel 75300,1166 Dave, I think you're right about not being sure you can _always_ check only Ah>0 for error detection on Int 13 returns. There's at least one case that always returns Ah=0, and the only error indication is carry set -- service 8. Most of my docs for the other services say that error codes will be returned in Ah, but I seem to remember not receiving error codes on some service 5 calls where I was asking for more sectors than the 1E vector supported (before I knew I had to set it), and it was only by a subsequent read or verify call that I detected the problem. -Charley #: 412143 S0/Outbox File 16-Mar-92 21:03:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70933 To: Jim Mack 76630,2012 Jim, When you say reset call, you mean just a 13/0 to drive 0? I'll give it a try. The other thing that took away the brrraaapp sound was just to reset 40:90 to the as-booted value, which turned out be 2 ("trying 1.2M media in 1.2M drive"). Now the test will be how it works on some other systems! These BIOS problems are a lot like the Times crosswords puzzles -- esoteric hints, and some of the words aren't in anybody's dictionary. Good idea to recreate and check the DBT. If I dont break it! -Charley #: 413291 S0/Outbox File 17-Mar-92 16:11:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70942 To: frank burleigh 72730,1017 Frank, I think you've got the simplest solution. I have now done it that way on your advice, along with saving the 2-byte media at 40:90, and have had NO trouble at all on exit. -Charley #: 413302 S0/Outbox File 17-Mar-92 16:22:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 70933 To: Jim Mack 76630,2012 Jim, I wasn't able to sort out the noise, but indeed I think I had nulled the double-stepping bit and the head was bangin' against the stop. I've watched carefully what my BIOS does with the 40:90 area. I dont know why I should be amazed, but it really does keep the media byte up-to-date! It will update it on a sector read, write or verify, as long as you repeat the operation after changing the disk to clear the "change line active" error. (Actually, BIOS nulls the "media type known" bit on the first call to service 2, 3 or 4 after a disk change, and then updates it to the new format on the second call.) And, regardless of the disk type being read, written or verified, 1Eh _always_ points to a copy of the DPT for the 1.44M format. I havent watched yet with my newly attuned eyes how the DOS format program changes the 1E pointer, but it stays the same for every other operation. I've updated the little writeup at BIOS13.TXT, if you want to edit/criticize. -Charley #: 71105 S1/Assembler [P] [IBMPRO] 18-Mar-92 11:19:33 Sb: #71028-BIOS Problem - Pt 2 Fm: frank burleigh 72730,1017 To: Charles F. Martin 72130,1400 Have you found that it is necessary to change the BIOS' data area in that way? I have not and, at present, everything works well. I have the sense that the BIOS will do whatever changing of its data area is required based on the service requests it receives (from us). Otherwise it seems we'd be doing its work for it. Sure, we can pool what knowledge we've learned and others can benefit. I will get the text file you mentioned. #: 414899 S0/Outbox File 18-Mar-92 18:59:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 71105 To: frank burleigh 72730,1017 Frank, On third thought, you are right, and I'm not sure why I concluded I ought to save the data at 40:90 -- just the 1E pointer. It's working just fine for me that way, too. Don't know what happened with bios13.txt; I'll look tonight and if not there re-upload. -Charley #: 71296 S1/Assembler [P] [IBMPRO] 21-Mar-92 01:56:09 Sb: #71130-BIOS Problem - Pt 2 Fm: frank burleigh 72730,1017 To: Charles F. Martin 72130,1400 Charles, BIOS13.TXT is looking good. We might come up with an outline of the procedure to format a diskette and append it to the text. 1. As it seems unnecessary to touch the value of 40:90, we might just limit the discussion of it to its interpretation. 2. One should probably interrogate 13h/15h and 13h/16h to test disk changes. I would suppose that if the drive doesn't have change status logic that the interpretation of this bit in 40:90 could lead one astray. Q: what happens if the BIOS doesn't support these two functions--what will happen when they are invoked? 3. On 13h/18h: if the function fails (carry) with a return code of 1 (not supported), then perhaps one may still go on under the presumption that int 1Eh already points to the single base table applicable to the drive (e.g., 360k). 4. Refs don't consistently say what to do with AL in calls to the format service (13h/5). Apparently AL should be the number of sectors on the track. On an IBM AT I found that the service would always fail (AH=9) unless AL was set to a count of sectors. 5. BIOS service failure and failure to reliably report failure: so what we're left with the implication that the safest bet is a test of carry *and* AH after a service request? 6. On DMA pages: the text makes the point that the Tandy BIOS requires the track fields to lie in an area the size of a full track. Dave Angel brought this point to my attention as a more general problem, so perhaps the text could be couched more generally: "some BIOSes" require *any* memory area to be the size of a full track and that that area must fit within one DMA page. We should go on to say how one gets such a block (i.e., get a block twice the needed size; discover if the first or second half fits in a DMA page; use a pointer to the half that does). #: 71318 S1/Assembler [P] [IBMPRO] 21-Mar-92 11:54:18 Sb: #71296-BIOS Problem - Pt 2 Fm: Jim Mack 76630,2012 To: frank burleigh 72730,1017 Frank - Regarding your point 5: sometimes the BIOS doesn't indicate an error because it doesn't consider what happened to -be- an error. For example, it's not considered an error to transfer fewer sectors than were requested, if the reason is that the buffer crossed a page boundary. It's incumbent on the programmer to note if there were any untransferred sectors and to initiate a second transfer for them using a normalized address (next page). This is one major difference between INT 25/26 and INT 13: the former do all this behind the scenes. On point 6... I do something similar to insure that I have an "even-page" buffer: alloc 128K, compute a huge pointer to it, ADD/AND to create DMA page alignment (there will always be one in any 128K block). Speaking of buffer "halves" is not quite right, since the page can split the buffer anywhere. -- Jim #: 418842 S0/Outbox File 21-Mar-92 12:42:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 71318 To: Jim Mack 76630,2012 Jim- Also re point 5 - Sometimes BIOS also reacts to something as tho it were an error, but it really is an advisory. Having made that grand statement, my example is "change line active". The service call that encounters this condition returns Ah=6 & carry, but its really an advisor to the programmer to let him decide if its OK to proceed with new media. Re point 6 - In the applications I've been writing I usually want to mass transfer a lot of disk at a time. I get all the memory available, and set up a segment table of the number of tracks I want to handle. The first pointer is the segment returned by the memory allocation request, the next is that plus the number of paragraphs in a track. If the result of this addition puts the next pointer over a 64k boundary, I go back and adjust the previous pointer to the beginning of the 64k segment, and proceed. Asking for one extra pointer gets the last pointer in bounds, and then subtracting the first pointer and comparing the result with the paras allocated tells you if enuff memory available to do the bulk transfer. -Charley #: 71330 S1/Assembler [P] [IBMPRO] 21-Mar-92 14:26:17 Sb: #71327-BIOS Problem - Pt 2 Fm: Jim Mack 76630,2012 To: Charles F. Martin 72130,1400 Charley - The main thing is segment alignment vs. DMA page alignment. A DMA page is naturally seg aligned but the opposite isn't true, and that can catch you with INT 13H... you start a transfer at a segment boundary, only to have it return with fewer than the requested number of sectors transferred (no error) even though there's plenty of room left in the segment. It "makes no sense" until you consider the DMA page. That's why I usually start by page-normalizing a linear address... it's automatic and you never need more than 128K. FWIW, once you know where the page falls you can shrink your block about 32K on average. If the most you'll need is a track's worth, you can use the linear address to compute the lowest usable segment value and release the rest. Getting all available memory is probably overkill. I've found that it's tough to outperform a series of individual "page-segment" transfers. Have you found otherwise? -- Jim #: 419961 S0/Outbox File 22-Mar-92 7:21:00 Sb: BIOS Problem - Pt 2 Fm: IBMPRO REP 71330 To: Jim Mack 76630,2012 Jim - I agree on overkill re getting all the memory, most of the time. It's just that for the programs I was working on when I ran into the original problem (waaaay back at the beginning of this thread) I set up to do bulk transfers. Eg, one program called COPY-360 reads an entire 360k disk into memory, then makes as many dups as you wish from that one master image in RAM. So my strategy was to create pointers to 80 track-side data areas 512 bytes x 9 sectors = 4.5k each, and read the disk in one pass: Track 0, head 0; trtack0, head 1; track 1, head 0; etc. Since I didn't need memory for anything else, and since there's a good chance there wont be enough, depending on what else is resident, I ask for it all, then calculate the pointers to each track-side so no DMA page boundary crossed (thanks for that term, BTW). When you get to the last pointer, you can tell if there was enough RAM originally, but you cant reliably tell until you create the table. (You can come pretty close -- 64k/4.5k= 14 track sides per DMA page, if strart at boundary.) The companion is COPY-ANY, works (theoreetically w/ any format, still testing...) but dividing disks into 2 or 4 "clumps", depending on initial format, making image to hard disk vice conventional RAM. Be glad to send to you for test/inspection if you like. Thanks, -Charley #: 71369 S1/Assembler [P] [IBMPRO] 22-Mar-92 08:55:28 Sb: #71367-BIOS Problem - Pt 2 Fm: Jim Mack 76630,2012 To: Charles F. Martin 72130,1400 Charley - I see now the requirement for 'all the memory'. I've done the same routines, though not as a complete product but as part of a commercial library for DOS and Windows. Format/copy/verify, DOS/EMS memory image, HD image or direct floppy-floppy of 360k through 2.88m. Fun, ain't it? In this case I took a different approach. Since DMA alignment can cause big slack-space problems with larger formats (and consider that the EMS page frame might be at, say, DC00), I ignore the issue and just try a whole track every time. When INT 13 says it didn't do all sectors, I adjust the pointer and try the remainder. This continues until I get no remainder (often just once). Then I can re-enter the track loop. The performance hit is minimal, and I can use any memory to nearly 100% (I do sector-align it if needed). -- Jim #: 74 S0/CompuServe Mail [MAIL] 22-Mar-92 16:32 EST Sb: BIOS13 Comments Fm: Ron Smith [71620,514] Charley Martin, A few notes that I had from developing a device driver that supports 720KB diskette formats with a 5 1/4" diskette in a 1.2MB drive. All they do is provide a bit more detail. You must check if your request would cross a real-memory 64k address boundary. The DMA controller in many PCs does not allow that. The hardware on many PCs and all 8088-based PCs only uses a 16-bit counter in the DMA when transferring data. While the DMA supports at least 20-bit addresses, it only increments the lower 16 bits. This means that no transfer can cross a 64K real address boundary. Note: Verify is like a read but no data transfer actually takes place. However, the BIOS still sets up the DMA and checks for requests spanning the 64K boundary and returns an error if one does. The BIOS state machine uses a byte at 40H:90H (plus physical drive number) to indicate the current state. It uses this information to try the operation. If the operation fails, it may try other state values to see if a different media is now being used. The BIOS state machine assigns the following values to the bits: Bits 0 - 2 = 0 - 360KB media in 360KB drive unestablished 1 - 360KB media in 1.2MB drive unestablished 2 - 1.2MB media in 1.2MB drive unestablished 3 - 360KB media in 360KB drive established 4 - 360KB media in 1.2MB drive established 5 - 1.2MB media in 1.2MB drive established Bit 3 = Reserved Bit 4 = 0 - Media/drive unestablished 1 - Media/drive established Bit 5 = 0 - Double stepping not required 1 - Double stepping required (360KB media in 1.2MB drive) Bits 6 - 7 = Transfer rate for this Media/drive 0 - 500 KBS (1.2MB media in 1.2MB drive) 1 - 300 KBS (360KB media in 1.2MB drive) 2 - 250 KBS (360KB media in 360KB drive) Established means that the BIOS thinks that it has correctly determined the media type. It always believes it knows what kind of drive it is dealing with. If the media type is unestablished and the drive is a 1.2MB type, the BIOS will retry the operation using the other media type. If it is established, it will simply return and error status. The change-line and reset functions cause the BIOS to set the media type to unestablished. Ron Smith #: 420820 S0/Outbox File 22-Mar-92 21:40:00 Sb: BIOS13 Comments Fm: MAIL To: Ron Smith [71620,514] Ron, Thanks for the feedback. I will fold it into the paper, which started out as "here are some tips" and is beginning to feel like a thesis! You illustrate a point, that there are some VERY competent guys out there whose brains need to be picked on subjects like this. Some of the behavior of the media byte during disk change I had kind of deduced just from trapping all the 13 calls and looking at 40:90 and 91. I have also found that the service 2,3 and 4 calls seem unaffected by changes in the int 1E pointer -- ie that the BIOS seems to consult the pointed-to DPT only to format. This is by deduction, am I right? I didn't realize that the verify call needed a pointer that wouldnt cross a 64k boundary too. Good thing to know. I always thought it was just the data-transferring services. -Charley #: 422269 S0/Outbox File 23-Mar-92 21:49:00 Sb: update on bios13 writeup Fm: MAIL To: frank burleigh 72730,1017 Hi, Frank, I haven't been ignoring your last message with 6 good points, but things just got a little hectic for a while. You should have a zip file of the latest draft by separate upload/download, but I haven't done your observations justic yet. I think the writeup covers 1, 5 and 6 from your 3/21 01:56 message reasonably well, but the idea of this paper is to take some time and give those who follow a complete discussion, so if I've missed any of the points you were making hit me again. On 4 (Al in 13h/5) I think the docs are fairly clear that it should be number of sectors to format, even tho DPT *and* the 13h/18h call specify already. But not to leave it unsaid, there is some code that illustrates format call. I need yet to figure how to work 2 and 3 in. Good question about whether BIOS clears media byte "knowledge" bit when door is opened if drive does not have a reporting change line. I think the answer may be that the BIOS doesn't care -- the change line service was added for programmers to be able to detect disk changes at critical times and prevent catastrophic overwrites of the wrong disk. For applications like dBASE that rewrite the FAT/ dir table, and cant tolerate disk changes in mid-application? Will finish this one day! -Charley #: 90 S0/CompuServe Mail [MAIL] 29-Mar-92 12:19 EST Sb: BIOS13 Comments Fm: Ron Smith [71620,514] Charley, Service 2, 3, and 4 calls do use the DPT as do reset calls. However, the values used by these calls are often constant across all the tables that you might use and thus the change of table does not noticeably affect the results. You have to be careful to keep INT 1EH pointing to a valid table though or all the calls except the status calls will stop working. The reset calls use the first two bytes of the table to tell the controller what drive parameters to use. These bytes contain drive performance specifics and hence don't vary from diskette to diskette. Since most drives that you could buy are built to the same performance specifics, they usually don't have to be changed even if you change drives. Calls 2, 3, and 4 use 6 or 7 of the bytes. While some of these are diskette sensitive, the BIOS logic doesn't use the full capabilities of the controller and hence can usually get away with the same values for all drives and diskettes. In case you don't have it, the format of the DPT is: DB SRT,HUT 4 bits each DB HLT,ND HLD is 7 bits, ND is 1 bit DB MOTOR_WAIT DB SEC_SIZE DB EOT DB GPL DB DTL DB GPL_FORMAT DB FILL DB HD_SETTLE DB MOTOR_START The first two bytes are sent to the controller on every reset operation and are unused at other times. SRT is the drive step rate in negative milliseconds. For 1.2MB drives the units are milliseconds. For 360KB drives the units are 2 milliseconds. Thus 0FH = 1 or 2 milliseconds respectively and 0EH = 2 or 4 milliseconds. HUT is the time it takes the head to unload after a read or write operation in positive 16 or 32 millisecond units. Thus 1 = 16 ms for a 1.2 MB drive or 32 ms for a 360KB drive. HLT is the time it takes the heads to load after the drive is selected in 2 or 4 millisecond units. For HLT 0 = 2 ms for a 1.2MB drive and 4 ms for a 360KB drive. ND, if set, puts the controller in non-data mode. The BIOS expects this bit to never be set. MOTOR_WAIT is the number of real-time clock interrupts to leave the motor on after an I/O operation (read, write, verify, format) has completed and is used by the BIOS on all those operations. SEC_SIZE is a power-of-2 indicator of the sector data size and is used on all I/O operations. It is also almost always a constant 2. The values are 0=128, 1=256, 2=512, 3=1024, ... EOT is the number of the last sector on a track. It is used on all I/O operations. However, due to the way the BIOS does I/O, it is OK for it to be bigger than the actual last sector except on format operations. Thus all the tables usually have it set to 15 or 18 and FORMAT establishes its own table with the exact value for use while formatting. Floppy disk controllers use this value to determine when they have reached the end of the track and should advance to the next head if they are currently doing head 0. IBM and all subsequent BIOSs have never used the controller's ability to read or write both heads in one operation and hence don't send the commands to the controller that make EOT meaningful. However, if EOT happens to be set too low, the controller will stop the transfer. So it is important to make sure that it is at least large enough. GPL is sent to the controller on read/write/verify operations. However, since it is different for each media and drive combination and the BIOS wants to be able to automatically adjust, most current BIOSs do not use the value in the DPT. Rather they calculate the value to use based on the determined media and the drive type. Thus changing GPL won't change the way most BIOSs operate. DTL is the data length. It is usually set to 0FFH which tells the controller to read/write/verify/format the number of bytes represented by the sector size. If you set it to a smaller number, the controller will skip the rest of the data in each sector. GPL_FORMAT is used only on format operations and specifies the inter-sector gap length to be used while formatting. FILL is the value to be written to the data area of each sector on a format operation. It is usually set to 0F6H, but you can set it to anything you want. I have also seen 0A5H or 05AH used (alternating 1 and 0 bits). HD_SETTLE is the amount of time to wait for the head to settle after a seek. With most current BIOSs it is calculated rather than being used from the table so that the BIOS can automatically adjust to multiple diskette drive types. It is specified in 1 millisecond units and the BIOS uses the value (usually calculated rather than from the table) in a loop after each seek. MOTOR_START is the amount of time in 1/8th second units that it takes the drive motor to get up to speed after being turned on. This is used in all I/O operations in a wait loop after turning the motor on. It is usually the same in all tables. Note that the BIOS does first check to see if the motor is already on and skips the wait loop if it is. Ron #: 430769 S0/Outbox File 29-Mar-92 19:29:00 Sb: BIOS13 Comments Fm: MAIL To: Ron Smith [71620,514] Ron, Thanks for the comments. You put a lot of time into that, and there is a _wealth_ of info there, so much so that I'd really like to cut and paste it into the treatise, with a Ron Smith byline, with your permission. I knew superficially what each of the bytes in the DPT represented, but your comments have revealed much if not all of the underlying architecture I and others would find very useful to know. Understanding how the BIOS diskette services for me up to now has been much like the way high energy physicists describe their trade. Like clashing together Swiss watches and deducing how they are constructed by the pieces that are ejected! Thanks again, and let me know. -Charley #: 98 S0/CompuServe Mail [MAIL] 01-Apr-92 23:11 EST Sb: BIOS13 Comments Fm: Ron Smith [71620,514] Charley, You are certainly welcome to use the information in any way that you choose. I can't take credit for any deep analysis for most of it. In fairness, you should really cite the IBM PC/AT Technical Reference Manual Copyright International Business Machines Corporation 1984 as the source of much of the information. It may be out of print now, but there is nothing with more detailed information that I have ever seen and I still refer to it frequently. It has complete listings of the PC/AT BIOS assembly code as well as descriptions of how many of the adapters work. I added a little experience with actually using the hardware-level interfaces that allowed me to read between some of the lines. Ron #: 448119 S0/Outbox File 10-Apr-92 20:39:00 Sb: bios.txt Fm: MAIL To: Frank Burleigh >INTERNET:burleigh@ogre.cica.indiana.edu Hi Frank! Thanks for the message and ther encouragement! I haven't worked on the bios13.txt in a while, I'm afraid, and I have some good comments to fold in from Ron Smith as well as yours. I think you just gave me the nudge to finish it up. >>AL shoould equal the number of sectors per track... I agree. The Phoenix book was okay on this, but seems like one I looked at a while back wasn't -- as was your more frustrating experience with Duncan's book. I'll do it! >>"3.5 is different" got mangled" -- I think I was _really_ tired when I wrote that! With no reluctance, I agree. Let me see if I can clean it up, but I think you got the point. The bios seems to look first for the hole, and if it's not there, will not permit the high density format, and vice versa. Ie, the format specified by the 18h call has to be the one supported by the diskette case. I'll bet you if you cover the hole in the 1.44M disk case, you will be able to format the disk to 720. I ended up discovering the need for that when I was trying to format some disks to 720 to exercise the diskcopy program I was writing at the start of all this, and needed to make some 720 dummies and only had holey cases. Nice to hear from you, Frank. I'll put the finishing touches on it this weekend with luck. Take care! -Charley